#
# landing.py - code for initial landing page for the application at its hosted root url
#
# Copyright 2008-2009 Autelic Association (http://www.autelic.org)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# import generic python stuff
import cgi
import os
import logging
import sys
import wsgiref.handlers

# Google App Engine (GAE) Pyhton libraries
from google.appengine.api import mail
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
import atom.url
import gdata.service
import gdata.alt.appengine

#import our own classes and functions
from constants import *
import pages

##################################### CODE ###############################################
# This is copied from google example code
def host_name_and_port():
   port = os.environ['SERVER_PORT']
   # if there is a defined port (other than the standard http port 80
   if port and port != '80':
     # then we need to add it to the returned hostname, so that URLs constructred with it work
     HOST_NAME_PORT = '%s:%s' % (os.environ['SERVER_NAME'], port)
   else:
     HOST_NAME_PORT = os.environ['SERVER_NAME']
   return HOST_NAME_PORT

# This URL maybe "called" upto three times for a login process on the HOME_DOMAIN
class landingHandler(webapp.RequestHandler):
  def get(self):
    # check if the user is already logged in to Google Account
    if (users.get_current_user() == None):
      # NOT logged in - STEP 0
      # if on HOME_DOMAIN then show a page to request an account
      if (os.environ['SERVER_NAME'] == HOME_URL):
         # prepare the welcome page, which will have a Sign in link in it
         page = pages.Page('please sign in or request a tutor account')

         # Resolve path to HTML form
         directory = os.path.dirname(__file__)
         path = os.path.join(directory, 'request_account_form.html')

         # add form to request a login account to this page
         template_values = {'error_message': self.request.get('error_message'), }
         page.add_html(template.render(path, template_values))

         # and show the page to the user
         self.response.out.write(page.show())
      else:
      	 # and send them to a login page then back here for STEp 1 - shown below
         self.redirect(users.create_login_url("/"))
    else:
      # Will pass by here for STEP 1 and for STEP 2 (with a token in URL)
      # try and find AuthSub 'token' in url
      try:
         # if we have a secure key, then use it to authenticate this site          
         rsa_key=open("keys/myraskey.pem", 'r').read()
      except:
         auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
      else:
         auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri, rsa_key)

      # initialize a client to talk to Google Data API services running on App Engine
      client = gdata.service.GDataService()
      gdata.alt.appengine.run_on_appengine(client)  

      # if there was no auth_sub token found in the URL, so we came from STEP 0, and this is STEP 1
      if not auth_token:   
         # STEP 1: Prepare a URL to send them back here for STEP 2
         next_url = atom.url.Url('http', host_name_and_port(), path='/')

         # define the list of scopes we want to get feeds from
         scopes = (CONTACTS_SCOPE+('%s/' % users.get_current_user().email()), PICASA_SCOPE)

         url = client.GenerateAuthSubURL(next_url, scopes, secure=False, session=True,
                                         domain=HOME_DOMAIN)

         # redirect back to this same URL, for STEP 2
         self.redirect(str(url))
      else:
         # STEP 2: logged-in AND token in the url, so have come BACK from AuthSub page
         # Convert AuthSub token to session token and store in user
         session_token = client.upgrade_to_session_token(auth_token)

         # Store a long-lived token for this user
         if session_token:
            client.token_store.add_token(session_token)
      
	 # and send them to the control panel
         self.redirect("/in/cpanel")

# End of 'landingHandler'
########################################################

# TODO separate into a separate more generic source module for sending e-mail
########################################################
# PostMail
class PostMail(webapp.RequestHandler):
  """Handles posting mail to recipient.
  Main form handler.  Merely receives fields and passes them to the
  EmailMessage class.
  """

  def handle_error(self, message):
    """
    Places the error message in to the request and redirects the
    user back to the index page, which redisplays the form with the error message
    shown
    TODO figure out how to refill the form with entered data
    """
    # TODO I thibk we could just send to '/' with error message as is same handler
    self.redirect('/error?error_message=%s' % message)

  # this gets run when the 'send' page is requested
  def get(self):

    directory = os.path.dirname(__file__)

    # Copy a subset of the form to the mail templates parameter
    # dict.
    values = dict((k, cgi.escape(self.request.get(k))) for k in (
        'first_name',
        'last_name',
        'email_address',
        'message'))

    if not values['first_name'].strip():
      self.handle_error('You must enter your first name!')
      return

    if not values['last_name'].strip():
      self.handle_error('You must enter your last name!')
      return

    if not values['email_address'].strip():
      self.handle_error('You must enter your e-mail address!')
      return
      
    if not values['message'].strip():
      self.handle_error('Please enter a message explaining your request.')
      return

#TODO doesn't seem to work
    if not mail.is_email_valid(values['email_address']):
      self.handle_error('Please enter a valid e-mail address.')
      return
 
    # Generate an EmailMessage object without a body.
    try:
      email_message = mail.EmailMessage(
                      sender=self.request.get('email_address'),
                      to=REQUEST_INBOX,
                      subject='Request for Tutor Account (Demo App)')

      # Report who really sent the email.
      email_message.reply_to = self.request.get('email_address')

      # Generate the body depending on format selection.
      # For each option, the templating engine is called to render
      # the mail body.
      template_file = os.path.join(directory, 'request_email.html')
      email_message.html = template.render(template_file, values, _DEBUG)

      email_message.check_initialized()

    except mail.InvalidEmailError:
      self.handle_error('Internal error, please e-mail' + REQUEST_INBOX + 'manually.')
      return
    except mail.MissingRecipientsError:
      self.handle_error('You must provide a recipient.')
      return
    except mail.MissingBodyError:
      self.handle_error('Internal error, please e-mail' + REQUEST_INBOX + 'manually.')
      return

    # go ahead and send it
    email_message.send()

    # Get the MIME e-mail sent to show to the user
    values['mime_message'] = cgi.escape(str(email_message.ToMIMEMessage()))

    # Render the sent page.
    path = os.path.join(directory, 'sent.html')
    self.response.out.write(template.render(path, values, _DEBUG))
 
    # TODO
    # also send an e-mail confirmation of sending to the requstor's e-mail address
  
# end of PostMail
#######################################################
    
def main(argv):
  application = webapp.WSGIApplication(
    [('/', landingHandler),
     ('/error', landingHandler),
     ('/send', PostMail)],
    debug=True)
    
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main(sys.argv)
